package bgpemulation;

import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;

public class BGPRoutingTable extends CIDRMap<PriorityQueue<ASPath>>{
	
	private static final long serialVersionUID = 1L;

	@Override
	public PriorityQueue<ASPath> makeEntry(String value) {
		PriorityQueue<ASPath> entry = new PriorityQueue<ASPath>();
		entry.add(new ASPath(value));
		return entry;
	}

	@Override
	public boolean updateValue(PriorityQueue<ASPath> oldValue, String value) {
		ASPath newPath = new ASPath(value);
		if(oldValue.contains(newPath)){
			return false;
		}
		ASPath prevHead = oldValue.peek();
		oldValue.add(newPath);
		clean(oldValue);
		return prevHead.equals(oldValue.peek());
	}

	private void clean(PriorityQueue<ASPath> oldValue) {
		List<ASPath> paths = new LinkedList<ASPath>(oldValue);
		oldValue.clear();
		for(ASPath p : paths){
			boolean bestPath = true;
			for(ASPath q : paths){
				bestPath &= bestPath(p, q);
			}
			if(bestPath){
				oldValue.add(p);
			}
		}
	}

	private boolean bestPath(ASPath p, ASPath q) {
		if(p.getHead() == q.getHead()){
			if(p.compareTo(q) <= 0){
				return true;
			}
			return false;
		}
		return true;
	}

	@Override
	public boolean remove(CIDRPrefix p, String value) {
		PriorityQueue<ASPath> paths = prefixes.get(p.getPrefixLength()).get(p);
		if(paths==null){
			return false;
		}
		boolean ret = paths.remove(new ASPath(value));
		if(paths.isEmpty()){
			delete(p);
		}
		return ret;
	}

	@Override
	public void print(PriorityQueue<ASPath> t) {
		if(t==null){
			System.out.println("\tERROR!!!");
			return;
		}
		List<ASPath> paths = new LinkedList<ASPath>();
		ASPath path;
		while((path = t.poll())!=null){
			paths.add(path);
			System.out.print("\t");
			path.print();
		}
		for(ASPath p : paths){
			t.add(p);
		}
	}

}
